package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.DesignBase;
import com.ruoyi.system.domain.DesignScheme;
import com.ruoyi.system.domain.DesignSchemeImage;
import com.ruoyi.system.dto.ProjectAttachmentDownloadDTO;
import com.ruoyi.system.entity.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.DesignBaseService;
import com.ruoyi.system.service.DesignSchemeService;
import com.ruoyi.system.service.IProjectAttachmentService;
import com.ruoyi.system.vo.ProjectAttachmentGroupVO;
import com.ruoyi.system.vo.ProjectAttachmentVO;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 项目附件服务实现类
 *
 * @author ruoyi
 * @since 2024-01-01
 */
@Service
public class ProjectAttachmentServiceImpl implements IProjectAttachmentService {

    @Resource
    private DesignSchemeImageMapper designSchemeImageMapper;

    @Resource
    private DesignSchemeService designSchemeService;

    @Resource
    private DesignBaseService designBaseService;

    @Resource
    private DesignBasicInformationGenMapper designBasicInformationMapper;

    @Resource
    private ContractFileMapper contractFileMapper;

    @Resource
    private ContractMapper contractMapper;

    @Resource
    private ConstructionItemMapper constructionItemMapper;

    @Resource
    private ProjectMapper projectMapper;

    @Override
    public List<ProjectAttachmentGroupVO> getProjectAttachmentsByGroup(Long projectId) {
        List<ProjectAttachmentVO> allAttachments = getProjectAttachments(projectId);

        // 按附件类型分组
        Map<Integer, List<ProjectAttachmentVO>> groupedAttachments = allAttachments.stream()
                .collect(Collectors.groupingBy(ProjectAttachmentVO::getAttachmentType));

        List<ProjectAttachmentGroupVO> result = new ArrayList<>();

        // 定义附件类型映射
        Map<Integer, String> typeNameMap = new HashMap<>();
        typeNameMap.put(1, "设计附件");
        typeNameMap.put(2, "合同附件");
        typeNameMap.put(3, "施工附件");
        typeNameMap.put(4, "验收附件");
        typeNameMap.put(5, "主材附件");

        for (Map.Entry<Integer, List<ProjectAttachmentVO>> entry : groupedAttachments.entrySet()) {
            ProjectAttachmentGroupVO group = new ProjectAttachmentGroupVO();
            group.setAttachmentType(entry.getKey());
            group.setAttachmentTypeName(typeNameMap.get(entry.getKey()));
            group.setCount(entry.getValue().size());
            group.setAttachments(entry.getValue());
            result.add(group);
        }

        // 按附件类型排序
        result.sort(Comparator.comparing(ProjectAttachmentGroupVO::getAttachmentType));

        return result;
    }

    @Override
    public List<ProjectAttachmentVO> getProjectAttachments(Long projectId) {
        List<ProjectAttachmentVO> allAttachments = new ArrayList<>();

        // 1. 获取设计附件
        allAttachments.addAll(getDesignAttachments(projectId));

        // 2. 获取合同附件
        allAttachments.addAll(getContractAttachments(projectId));

        // 3. 获取施工附件
        allAttachments.addAll(getConstructionAttachments(projectId));

        // 4. 获取验收附件
        allAttachments.addAll(getAcceptanceAttachments(projectId));

        // 5. 获取主材附件
        allAttachments.addAll(getMaterialAttachments(projectId));

        // 按创建时间倒序排序
//        allAttachments.sort(Comparator.comparing(ProjectAttachmentVO::getCreateTime).reversed());

        return allAttachments;
    }

    @Override
    public List<ProjectAttachmentVO> getProjectAttachmentsByType(Long projectId, Integer attachmentType) {
        switch (attachmentType) {
            case 1:
                return getDesignAttachments(projectId);
            case 2:
                return getContractAttachments(projectId);
            case 3:
                return getConstructionAttachments(projectId);
            case 4:
                return getAcceptanceAttachments(projectId);
            case 5:
                return getMaterialAttachments(projectId);
            default:
                throw new ServiceException("不支持的附件类型: " + attachmentType);
        }
    }

    @Override
    public void downloadProjectAttachments(ProjectAttachmentDownloadDTO downloadDTO, HttpServletResponse response) {
        try {
            // 获取要下载的附件信息
            List<ProjectAttachmentVO> selectedAttachments = getProjectAttachments(downloadDTO.getProjectId());

            if (selectedAttachments.isEmpty()) {
                throw new ServiceException("没有找到要下载的附件");
            }

            // 设置响应头
            String zipFileName = downloadDTO.getZipFileName();
            if (!StringUtils.hasText(zipFileName)) {
                zipFileName = "项目附件_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".zip";
            }

            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipFileName, StandardCharsets.UTF_8.toString()));

            // 创建ZIP输出流
            try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
                if (downloadDTO.getDownloadType() == 1) {
                    // 按分类打包
                    downloadByCategory(selectedAttachments, zipOut);
                } else {
                    // 全部打包为一个文件
                    downloadAllInOne(selectedAttachments, zipOut);
                }
            }

        } catch (Exception e) {
            throw new ServiceException("下载失败: " + e.getMessage());
        }
    }

    /**
     * 获取设计附件
     */
    private List<ProjectAttachmentVO> getDesignAttachments(Long projectId) {
        List<ProjectAttachmentVO> attachments = new ArrayList<>();

        try {
            List<DesignBase> list = designBaseService.lambdaQuery()
                    .eq(DesignBase::getProjectId, projectId)
                    .list();
            List<DesignScheme> schemes = designSchemeService.lambdaQuery()
                    .in(DesignScheme::getDesignBaseId, list.stream().map(DesignBase::getId).collect(Collectors.toList()))
                    .eq(DesignScheme::getIsAdopted, 1)
                    .list();

            for (DesignScheme scheme : schemes) {
                // 3. 获取设计图片
                List<DesignSchemeImage> images = designSchemeImageMapper.selectBySchemeId(scheme.getId());

                for (DesignSchemeImage image : images) {
                    ProjectAttachmentVO attachment = new ProjectAttachmentVO();
                    attachment.setId(image.getId());
                    attachment.setFileName(image.getFileName());
                    attachment.setOriginalName(image.getFileName());
                    attachment.setFileType(image.getFileType());
                    attachment.setFileSize(image.getFileSize());
                    attachment.setFilePath(image.getFilePath());
                    attachment.setDownloadUrl(image.getFilePath());
                    attachment.setAttachmentType(1);
                    attachment.setAttachmentTypeName("设计附件");
                    attachment.setBusinessId(scheme.getId());
                    attachment.setBusinessName(scheme.getSchemeName());
                    attachment.setSpaceType(image.getSpaceType());
                    attachment.setSortOrder(image.getSortOrder());
                    attachment.setUploadBy("系统"); // 设计图片通常由系统导入
                    attachment.setCreateTime(image.getCreatedTime());
                    attachment.setUpdateTime(image.getCreatedTime());
                    attachments.add(attachment);
                }
            }

        } catch (Exception e) {
            // 记录日志但不影响主流程
            System.err.println("获取设计附件时发生异常: " + e.getMessage());
        }

        return attachments;
    }

    /**
     * 获取合同附件
     */
    private List<ProjectAttachmentVO> getContractAttachments(Long projectId) {
        List<ProjectAttachmentVO> attachments = new ArrayList<>();

        try {
            // 1. 获取项目关联的合同
            List<ContractDO> contracts = contractMapper.selectList(
                    new LambdaQueryWrapper<ContractDO>()
                            .eq(ContractDO::getProjectId, projectId)
                            .eq(ContractDO::getIsDeleted, 0)
            );

            for (ContractDO contract : contracts) {
                // 2. 获取合同附件
                List<ContractFile> contractFiles = contractFileMapper.selectList(
                        new LambdaQueryWrapper<ContractFile>()
                                .eq(ContractFile::getContractId, contract.getId())
                                .eq(ContractFile::getIsDelete, 0)
                                .orderByAsc(ContractFile::getId)
                );

                for (ContractFile file : contractFiles) {
                    ProjectAttachmentVO attachment = new ProjectAttachmentVO();
                    attachment.setId(file.getId());
                    attachment.setFileName(file.getFileName());
                    attachment.setOriginalName(file.getOriginalName());
                    attachment.setFileType(file.getFileType());
                    attachment.setFileSize(file.getFileSize());
                    attachment.setFilePath(file.getDownloadUrl());
                    attachment.setDownloadUrl(file.getDownloadUrl());
                    attachment.setAttachmentType(2);
                    attachment.setAttachmentTypeName("合同附件");
                    attachment.setBusinessId(contract.getId());
                    attachment.setBusinessName(contract.getContractName());
                    attachment.setUploadBy("系统"); // 合同附件通常由系统导入
                    attachment.setCreateTime(file.getCreateTime());
                    attachment.setUpdateTime(file.getCreateTime());
                    attachments.add(attachment);
                }
            }
        } catch (Exception e) {
            // 记录日志但不影响主流程
            System.err.println("获取合同附件时发生异常: " + e.getMessage());
        }

        return attachments;
    }

    /**
     * 获取施工附件
     */
    private List<ProjectAttachmentVO> getConstructionAttachments(Long projectId) {
        List<ProjectAttachmentVO> attachments = new ArrayList<>();

        try {
            // 获取施工事项的验收图片
            List<ConstructionProjectItemDO> items = constructionItemMapper.selectList(
                    new LambdaQueryWrapper<ConstructionProjectItemDO>()
                            .eq(ConstructionProjectItemDO::getProjectId, projectId)
                            .eq(ConstructionProjectItemDO::getIsDeleted, 0)
                            .isNotNull(ConstructionProjectItemDO::getAcceptImages)
                            .ne(ConstructionProjectItemDO::getAcceptImages, "")
            );

            for (ConstructionProjectItemDO item : items) {
                if (StringUtils.hasText(item.getAcceptImages())) {
                    try {
                        List<String> imageUrls = JSON.parseArray(item.getAcceptImages(), String.class);
                        for (int i = 0; i < imageUrls.size(); i++) {
                            String imageUrl = imageUrls.get(i);
                            ProjectAttachmentVO attachment = new ProjectAttachmentVO();
                            attachment.setId(item.getId() * 1000L + i); // 生成唯一ID
                            attachment.setFileName("验收图片_" + (i + 1) + ".jpg");
                            attachment.setOriginalName("验收图片_" + (i + 1) + ".jpg");
                            attachment.setFileType("image/jpeg");
                            attachment.setFilePath(imageUrl);
                            attachment.setDownloadUrl(imageUrl);
                            attachment.setAttachmentType(3);
                            attachment.setAttachmentTypeName("施工附件");
                            attachment.setBusinessId(item.getId());
                            attachment.setBusinessName(item.getItemName());
                            attachment.setUploadBy("系统");
                            attachment.setCreateTime(item.getUpdateTime());
                            attachment.setUpdateTime(item.getUpdateTime());
                            attachments.add(attachment);
                        }
                    } catch (Exception e) {
                        // 解析JSON失败时跳过
                        System.err.println("解析施工事项验收图片失败: " + e.getMessage());
                    }
                }
            }
        } catch (Exception e) {
            // 记录日志但不影响主流程
            System.err.println("获取施工附件时发生异常: " + e.getMessage());
        }

        return attachments;
    }

    /**
     * 获取验收附件
     */
    private List<ProjectAttachmentVO> getAcceptanceAttachments(Long projectId) {
        // 验收附件暂时返回空列表，后续可根据实际业务需求扩展
        return new ArrayList<>();
    }

    /**
     * 获取主材附件
     */
    private List<ProjectAttachmentVO> getMaterialAttachments(Long projectId) {
        // 主材附件暂时返回空列表，后续可根据实际业务需求扩展
        return new ArrayList<>();
    }

    /**
     * 按分类打包下载
     */
    private void downloadByCategory(List<ProjectAttachmentVO> attachments, ZipOutputStream zipOut) throws IOException {
        Map<Integer, List<ProjectAttachmentVO>> groupedAttachments = attachments.stream()
                .collect(Collectors.groupingBy(ProjectAttachmentVO::getAttachmentType));

        Map<Integer, String> typeNameMap = new HashMap<>();
        typeNameMap.put(1, "设计附件");
        typeNameMap.put(2, "合同附件");
        typeNameMap.put(3, "施工附件");
        typeNameMap.put(4, "验收附件");
        typeNameMap.put(5, "主材附件");

        for (Map.Entry<Integer, List<ProjectAttachmentVO>> entry : groupedAttachments.entrySet()) {
            String categoryName = typeNameMap.get(entry.getKey());
            for (ProjectAttachmentVO attachment : entry.getValue()) {
                String entryName = categoryName + "/" + attachment.getOriginalName();
                addFileToZip(attachment, entryName, zipOut);
            }
        }
    }

    /**
     * 全部打包为一个文件
     */
    private void downloadAllInOne(List<ProjectAttachmentVO> attachments, ZipOutputStream zipOut) throws IOException {
        for (ProjectAttachmentVO attachment : attachments) {
            String entryName = attachment.getOriginalName();
            addFileToZip(attachment, entryName, zipOut);
        }
    }

    /**
     * 添加文件到ZIP
     */
    private void addFileToZip(ProjectAttachmentVO attachment, String entryName, ZipOutputStream zipOut) throws IOException {
        ZipEntry zipEntry = new ZipEntry(entryName);
        zipOut.putNextEntry(zipEntry);

        // 这里需要根据实际的文件存储方式来实现文件读取
        // 如果是OSS存储，需要从OSS下载文件内容
        // 如果是本地存储，需要从本地文件系统读取
        // 这里先创建一个占位符文件
        String content = "文件: " + attachment.getOriginalName() + "\n" +
                "类型: " + attachment.getFileType() + "\n" +
                "大小: " + attachment.getFileSize() + " bytes\n" +
                "下载地址: " + attachment.getDownloadUrl() + "\n" +
                "上传时间: " + attachment.getCreateTime();

        zipOut.write(content.getBytes(StandardCharsets.UTF_8));
        zipOut.closeEntry();
    }
}
